package com.cls.business.controller;

import com.cls.business.entity.DeclarePlan;
import com.cls.business.entity.DeclareTopic;
import com.cls.business.entity.TopicPlan;

import com.cls.business.service.*;
import com.cls.business.service.impl.ExportExcelService;
import com.cls.business.vo.DeclareTopicVO;
import com.cls.business.vo.EvaluationResultVO;
import com.cls.business.vo.ExpertReviewResultVO;
import com.cls.common.annotation.ControllerEndpoint;
import com.cls.common.controller.BaseController;
import com.cls.common.entity.MyConstant;
import com.cls.common.entity.QueryRequest;
import com.cls.common.entity.ResponseVO;
import com.cls.common.enums.DictEnum;
import com.cls.common.exception.MyException;
import com.cls.common.utils.FileUtil;
import com.cls.common.utils.MyUtil;
import com.cls.common.utils.StringUtils;
import com.cls.system.entity.Expert;
import com.cls.system.entity.SysDict;
import com.cls.system.entity.SysFile;
import com.cls.system.entity.Template;
import com.cls.system.service.IExpertService;
import com.cls.system.service.ISysDictService;
import com.cls.system.service.ISysFileService;
import com.cls.system.service.ITemplateService;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 定评评审控制器
 *
 * @author wmm
 */
@Slf4j
@Validated
@Controller
@RequiredArgsConstructor
public class EvaluationController extends BaseController {

    private final IDeclareTopicService declareTopicService;

    private final IExpertExcel8ReviewService expertExcel8ReviewService;

    private final ISysDictService sysDictService;

    private final IReviewService reviewService;

    private final ITopicPlanService topicPlanService;

    private final IDeclarePlanService declarePlanService;

    private final IExpertService expertService;

    private final ISysFileService sysFileService;

    private final ITemplateService templateService;

    /**
     * 委托列表页面
     **/
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/evaluation/entrust")
    public String evaluationEntrustIndex(Model model) {
        List<SysDict> subjectType = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectType", subjectType);
        model.addAttribute("topicClassifyCode", DictEnum.ENTRUST.getCode());
        List<SysDict> planNos = sysDictService.findByParentCode(DictEnum.PLAN_NO.getCode());
        model.addAttribute("planNos", planNos);
        return MyUtil.view("business/entrust/evaluation/evaluation");
    }

    /**
     * 委托定级页面
     *
     * @param declareId
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/evaluation/entrust/defineLevel/{declareId}/{topicPlanId}")
    public String entrustDefineLevel(@PathVariable Long declareId, @PathVariable Long topicPlanId, Model model) {
        DeclareTopic declare = declareTopicService.getById(declareId);
        declare.setTopicPlanId(topicPlanId);
        model.addAttribute("declare", declare);
        //查询等级
        List<SysDict> levelType = sysDictService.findByParentCode(DictEnum.CONCLUDE_TOPIC_LEVEL_CODE.getCode());
        model.addAttribute("levelType", levelType);
        return MyUtil.view("business/entrust/evaluation/defineLevel");
    }

    /**
     * 委托定级
     *
     * @param declareTopic
     * @return
     */
    @ControllerEndpoint(operation = "委托定级", exceptionMessage = "委托定级失败")
    @PostMapping("biz/evaluation/entrust/defineLevel")
    @ResponseBody
    @RequiresPermissions("evaluation:update")
    public ResponseVO entrustDefineLevel(DeclareTopic declareTopic) {
        //需要先确定是否全部专家评审完毕
        //通过课题获取计划
        TopicPlan topicPlan = topicPlanService.getById(declareTopic.getTopicPlanId());
        DeclarePlan declarePlan = declarePlanService.findByDeclareTopicIdAndPlanId(declareTopic.getDeclareId(), declareTopic.getTopicPlanId());
        if (DictEnum.PLAN_REVIEW.getCode().equals(topicPlan.getStatusCode())) {
            //修改declareTopic表中的等级
            DeclareTopic update = new DeclareTopic();
            update.setDeclareId(declareTopic.getDeclareId());
            update.setFinalLevelTypeCode(declareTopic.getFinalLevelTypeCode());
            //修改declarePlan表中的等级
            declarePlan.setLevelTypeCode(declareTopic.getFinalLevelTypeCode());
            declarePlanService.updateById(declarePlan);
            //如果当前状态为不合格则修改状态为结项失败
            if (DictEnum.CONCLUDE_TOPIC_LEVEL_BHG.getCode().equals(declareTopic.getFinalLevelTypeCode())) {
                update.setStatusTypeCode(DictEnum.CONCLUDE_FAILED.getCode());
                //判断申请次数，如果是第二次申请则设置为课题周期完结
                Integer applyCount = declarePlan.getApplyCount();
                if (applyCount > 1) {
                    update.setIsFinish(true);
                }
            } else {
                update.setStatusTypeCode(DictEnum.CONCLUDE_PASSED.getCode());
                update.setIsFinish(true);
            }
            this.declareTopicService.updateById(update);
        } else {
            return ResponseVO.failure("对不起，当前状态不允许定级！");
        }
        return ResponseVO.success();
    }


    /**
     * 年度列表页面
     **/
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/evaluation")
    public String evaluationIndex(Model model) {
        List<SysDict> subjectType = sysDictService.findByParentCode(DictEnum.SUBJECT_TYPE.getCode());
        model.addAttribute("subjectType", subjectType);
        model.addAttribute("topicClassifyCode", DictEnum.ANNUAL.getCode());
        return MyUtil.view("business/evaluation/evaluation");
    }

    /**
     * 评审结果页面
     *
     * @param declareTopicId
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/evaluation/result/{declareTopicId}/{planId}")
    public String evaluationResult(@PathVariable Long declareTopicId, @PathVariable Long planId, Model model) {
        DeclarePlan declarePlan = declarePlanService.findByDeclareTopicIdAndPlanId(declareTopicId, planId);
        model.addAttribute("planId", planId);
        model.addAttribute("declareTopicId", declareTopicId);
        model.addAttribute("score", declarePlan.getPlanScore());
        return MyUtil.view("business/evaluation/result");
    }

    /**
     * 年度定级页面
     *
     * @param declareId
     * @return
     */
    @GetMapping(MyConstant.VIEW_PREFIX + "biz/evaluation/defineLevel/{declareId}/{topicPlanId}")
    public String defineLevel(@PathVariable Long declareId, @PathVariable Long topicPlanId, Model model) {
        DeclareTopic declare = declareTopicService.getById(declareId);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(declare.getFinalLevelTypeCode())) {
            //查询字典父code
            String parentCode = sysDictService.selectForParentCode(declare.getFinalLevelTypeCode()).getCode();
            declare.setParentFinalLevelTypeCode(parentCode);
        }
        declare.setTopicPlanId(topicPlanId);
        model.addAttribute("declare", declare);
        //查询课题分类
        List<Map<String, Object>> group_list = sysDictService.selectByParentCode(DictEnum.TOPIC_LEVEL_TYPE.getCode());
        Map<String, Object> map = new HashMap<>();
        map.put("groups", group_list);
        model.addAllAttributes(map);
        return MyUtil.view("business/evaluation/defineLevel");
    }

    @GetMapping("biz/evaluation/list")
    @ResponseBody
    @RequiresPermissions("evaluation:list")
    public ResponseVO evaluationList(QueryRequest request, DeclareTopic declareTopic) {
        //必须查询已评审后之后状态的信息方可能展示
        List<String> codes = new ArrayList<>();
        codes.add(DictEnum.CHECK_PASSED_EXPERT.getCode());
        codes.add(DictEnum.CHECK_PASSED_REVIEW.getCode());
        codes.add(DictEnum.PRE_ITEM.getCode());
        codes.add(DictEnum.ITEM_NO_CHECK.getCode());
        codes.add(DictEnum.ITEM_CHECK_PASSED.getCode());
        codes.add(DictEnum.ITEM_CHECK_FAILED.getCode());
        codes.add(DictEnum.ITEM_PASSED.getCode());
        codes.add(DictEnum.ITEM_FAILED.getCode());
        codes.add(DictEnum.ITEM_CANCEL.getCode());
        codes.add(DictEnum.CONCLUDE_FAILED.getCode());
        codes.add(DictEnum.CONCLUDE_PASSED.getCode());
        codes.add(DictEnum.CONCLUDE_ASSIGN.getCode());
        declareTopic.setStatusTypeCodes(codes);
        declareTopic.setPlanStatusTypeCode(DictEnum.PLAN_EXPERT.getCode());
        if (StringUtils.isNotBlank(declareTopic.getYear()) && StringUtils.isNotBlank(declareTopic.getPlanNo())) {
            declareTopic.setPeriod(declareTopic.getYear() + "-" + declareTopic.getPlanNo());
        } else if (StringUtils.isNotBlank(declareTopic.getYear())) {
            declareTopic.setPeriod(declareTopic.getYear());
        }
        PageInfo<DeclareTopicVO> declareTopics = this.declareTopicService.findDeclareTopicsForEvaluation(request, declareTopic);
        return ResponseVO.success(declareTopics);
    }


    /**
     * 查询评审结果数据
     *
     * @param declareId
     * @return
     */
    @GetMapping("biz/evaluation/review/{declareId}/{planId}")
    @ResponseBody
    public ResponseVO reviewList(@PathVariable Long declareId, @PathVariable Long planId) {
        PageInfo pageInfo = new PageInfo(reviewService.selectResultByDeclareId(declareId, planId));
        return ResponseVO.success(pageInfo);
    }

    /**
     * 查询专家的列
     *
     * @param declareId
     * @return
     */
    @GetMapping("biz/evaluation/review/column/{declareId}/{planId}")
    @ResponseBody
    public ResponseVO reviewColumn(@PathVariable Long declareId, @PathVariable Long planId) {
        List<Expert> expertVOS = reviewService.selectExpertByDeclareId(declareId, planId);
        return ResponseVO.success(expertVOS);
    }


    /**
     * 前端查询专家的列
     *
     * @param declareId
     * @return
     */
    @GetMapping("biz/evaluation/review/client/column/{declareId}/{planId}")
    @ResponseBody
    public ResponseVO reviewColumn4Client(@PathVariable Long declareId, @PathVariable Long planId) {
        List<Expert> expertVOS = reviewService.selectExpertByDeclareId(declareId, planId);
        for (int i = 0; i < expertVOS.size(); i++) {
            Expert expert = expertVOS.get(i);
            expert.setName("专家" + (i + 1));
        }
        return ResponseVO.success(expertVOS);
    }


    @ControllerEndpoint(operation = "定级", exceptionMessage = "定级失败")
    @PostMapping("biz/evaluation/defineLevel")
    @ResponseBody
    @RequiresPermissions("evaluation:update")
    public ResponseVO defineLevel(DeclareTopic declareTopic) {
        //需要先确定是否全部专家评审完毕
        //通过课题编号获取计划
        TopicPlan topicPlan = topicPlanService.getById(declareTopic.getTopicPlanId());
        if (DictEnum.PLAN_REVIEW.getCode().equals(topicPlan.getStatusCode())) {
            DeclareTopic update = new DeclareTopic();
            update.setDeclareId(declareTopic.getDeclareId());
            update.setFinalLevelTypeCode(declareTopic.getFinalLevelTypeCode());
            //状态修改为拟立项
            update.setStatusTypeCode(DictEnum.PRE_ITEM.getCode());
            this.declareTopicService.updateById(update);
        } else {
            return ResponseVO.failure("对不起，当前状态不允许定级！");
        }
        return ResponseVO.success();
    }

    /**
     * 魏起成
     * 导出评审结果
     *
     * @param
     * @param response
     */
    @ControllerEndpoint(operation = "导出评审结果", exceptionMessage = "导出Excel失败")
    @GetMapping("biz/evaluation/export/{classType}/{period}")
    @RequiresPermissions("evaluation:list")
    public void export(@PathVariable String period, @PathVariable String classType, HttpServletResponse response) {

        try {
            expertExcel8ReviewService.exportReviewResult(period, response, classType);
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyException("对不起，导出失败！");
        }
    }

    @ControllerEndpoint(operation = "结项鉴定结果表", exceptionMessage = "导出结项鉴定结果表失败")
    @GetMapping("biz/evaluation/exportEvaluationResult")
    @RequiresPermissions("evaluation:list")
    public void exportEvaluationResult(DeclareTopic declareTopic, HttpServletResponse response) {
        if (declareTopic.getYear() == null) {
            throw new RuntimeException("请填写正确的期次！");
        }
        String period = declareTopic.getYear();
        if (StringUtils.isNotEmpty(declareTopic.getPlanNo())) {
            period = declareTopic.getYear() + "-" + declareTopic.getPlanNo();
        }

        TopicPlan plan = new TopicPlan();
        plan.setPeriod(period);

        List<TopicPlan> topicPlans = topicPlanService.findTopicPlans(plan);
        if (topicPlans == null || topicPlans.size() != 1) {
            throw new RuntimeException("无数据！");
        }
        Long planId = topicPlans.get(0).getPlanId();
        List<EvaluationResultVO> results = declarePlanService.findEvaluationResultByPlanId(planId);
        if (results == null || results.size() < 1) {
            throw new RuntimeException("无数据！");
        }
        Map<String, String> dictLevelTypes = new HashMap();
        Map<String, List<EvaluationResultVO>> evaluationResults = new HashMap();
        for (EvaluationResultVO one : results) {
            String finalLevelTypeCode = one.getFinalLevelTypeCode();
            String name = dictLevelTypes.get(finalLevelTypeCode);
            if (StringUtils.isEmpty(name)) {
                SysDict dict = sysDictService.findByCode(finalLevelTypeCode);
                if (dict != null) {
                    name = dict.getName();
                    dictLevelTypes.put(finalLevelTypeCode, name);
                } else {
                    continue;
                }
            }
            List<EvaluationResultVO> lstEvaluationResult = evaluationResults.get(name);
            if (lstEvaluationResult == null) {
                lstEvaluationResult = new ArrayList();

            }
            lstEvaluationResult.add(one);
            evaluationResults.put(name, lstEvaluationResult);
        }

        Template template = templateService.findByTemplateTypeCode(DictEnum.TEMPLATE_CONCLUDE_RESULT.getCode());
        if (template == null) {
            throw new RuntimeException("模板文件不存在！");
        }
        SysFile sysFile = sysFileService.getById(template.getFileId());
        if (sysFile == null) {
            throw new RuntimeException("模板文件不存在！");
        }

        try {
            FileUtil.downloadExcel(ExportExcelService.exportEvaluationResult(evaluationResults, period, sysFile.getUrl()), response, URLEncoder.encode("filename11", "UTF-8"));
        } catch (Exception e) {
            throw new RuntimeException("下载失败！");
        }
    }


    @ControllerEndpoint(operation = "导出专家评审统计", exceptionMessage = "导出专家评审统计失败")
    @GetMapping("biz/evaluation/exportExpertReviewResult")
    @RequiresPermissions("evaluation:list")
    public void exportExpertReviewResult(DeclareTopic declareTopic, HttpServletResponse response) {
        if (declareTopic.getYear() == null) {
            throw new RuntimeException("请填写正确的期次！");
        }
        String period = declareTopic.getYear();
        if (StringUtils.isNotEmpty(declareTopic.getPlanNo())) {
            period = declareTopic.getYear() + "-" + declareTopic.getPlanNo();
        }

        TopicPlan param = new TopicPlan();
        param.setPeriod(period);

        List<TopicPlan> topicPlans = topicPlanService.findTopicPlans(param);
        if (topicPlans == null || topicPlans.size() != 1) {
            throw new RuntimeException("数据异常！");
        }
        TopicPlan plan = topicPlans.get(0);
        Long planId = plan.getPlanId();
        Long standardId = plan.getStandardId();
        List<ExpertReviewResultVO> results = reviewService.selectReviewByPlanIdAndStandardId(planId, standardId);
        if (results == null || results.size() < 1) {
            throw new RuntimeException("无数据！");
        }
        Map<Long, String> experts = new HashMap();
        Map<Long, Map<Long, ExpertReviewResultVO>> reviewResults = new HashMap();
        for (ExpertReviewResultVO one : results) {
            Long expertId = one.getExpertId();
            if (experts.get(expertId) == null) { // 专家ID与名字对应关系
                Expert expert = expertService.findById(expertId);
                if (expert != null) {
                    experts.put(expertId, expert.getName());
                }
            }
            Map<Long, ExpertReviewResultVO> lstEvaluationResult = reviewResults.get(expertId);
            if (lstEvaluationResult == null) { //
                lstEvaluationResult = new HashMap();
                List<String> scores = new ArrayList();
                scores.add(one.getScore());
                one.setScores(scores);
                lstEvaluationResult.put(one.getDeclareId(), one);
                reviewResults.put(expertId, lstEvaluationResult);
            } else {
                ExpertReviewResultVO temp = lstEvaluationResult.get(one.getDeclareId());
                if (temp != null) {
                    List<String> scores = temp.getScores();
                    if (scores != null) {
                        scores.add(one.getScore());
                    }
                } else {
                    List<String> scores = new ArrayList();
                    scores.add(one.getScore());
                    one.setScores(scores);
                    lstEvaluationResult.put(one.getDeclareId(), one);
                }
            }
        }

        Template template = templateService.findByTemplateTypeCode(DictEnum.TEMPLATE_EXPERT_REVIEW.getCode());
        if (template == null) {
            throw new RuntimeException("模板文件不存在！");
        }
        SysFile sysFile = sysFileService.getById(template.getFileId());
        if (sysFile == null) {
            throw new RuntimeException("模板文件不存在！");
        }

        try {
            FileUtil.downloadExcel(ExportExcelService.exportExpertReviewResult(reviewResults, experts, period, sysFile.getUrl()), response, URLEncoder.encode("filename11", "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据申请课题id查询所有的计划
     */
    @GetMapping("biz/evaluation/getAllPlanIdByDeclareTopicId/{declareTopicId}")
    @ResponseBody
    public ResponseVO getAllPlanIdByDeclareTopicId(@PathVariable Long declareTopicId) {
        List<DeclarePlan> declarePlans = declarePlanService.getAllPlanIdByDeclareTopicId(declareTopicId);
        return ResponseVO.success(declarePlans);
    }



}
